<script lang="ts">
import {
  defineComponent,
  onMounted,
  reactive,
  toRefs,
  type PropType
} from 'vue'
import {
  FormItemConfig
} from '@/types/loginForm.ts'
import {
  ElMessage
} from 'element-plus'

type LabelPosition = 'left' | 'top'


export default defineComponent({
  name: 'LoginForm',
  emits: ['sendMsgPhone', 'sendMsgMail', 'getCode', 'submit'],
  props: {
    labelShow: {
      type: Boolean,
      default: false
    },
    labelPosition: {
      type: String as PropType<LabelPosition>,
      default: 'top',
      validator: (value: unknown) => {
        return typeof value === 'string' && ['left', 'top'].includes(value as LabelPosition)
      }
    },
    componentList: {
      type: Array as PropType<FormItemConfig[]>,
      required: true,
      validator: (value: FormItemConfig[]) => {
        return value.every(item => ['input', 'password', 'phone', 'email', 'code'].includes(item.type))
      }
    },
    submitText: {
      type: String,
      default: '登录'
    }
  },
  setup(props, {emit}) {
    const state = reactive({
      form: {} as Record<string, null>
    })

    const isPhoneNumber = (phone: string): boolean => {
      return /^1[3-9]\d{9}$/.test(phone)
    }

    const isValidEmail = (email: string): boolean => {
      return /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email)
    }

    const makeForm = () => {
      state.form = props.componentList.reduce((acc, item) => {
        return {...acc, [item.prop]: null}
      }, {} as Record<string, null>)
      console.log(state.form)
    }

    onMounted(() => {
      makeForm()
    })

    const handlePhoneSendMsg = (item: FormItemConfig) => {
      if (state.form[item.prop] != null){
        if (isPhoneNumber(state.form[item.prop]!)) {
          emit('sendMsgPhone', item.prop, state.form[item.prop])
        } else {
          ElMessage.warning('请输入正确的手机号!')
        }
      } else {
        ElMessage.warning('请输入正确的手机号!')
      }
    }

    const handleMailSendMsg = (item: FormItemConfig) => {
      if (state.form[item.prop] != null){
        if (isValidEmail(state.form[item.prop]!)) {
          emit('sendMsgMail', item.prop, state.form[item.prop])
        } else {
          ElMessage.warning('请输入正确的邮箱!')
        }
      } else {
        ElMessage.warning('请输入正确的邮箱!')
      }
    }

    const handleGetCode = (item: FormItemConfig) => {
      emit('getCode', item.prop)
    }

    const handleSubmit = () => {
      emit('submit', {...state.form})
    }

    return {
      ...toRefs(state),
      handlePhoneSendMsg,
      handleMailSendMsg,
      handleGetCode,
      handleSubmit
    }
  }
})
</script>

<template>
  <div class="component-login-form-container">
    <el-form :label-position="labelPosition" :model="form" :label-suffix="labelShow ? ':' : ''">
      <el-form-item :label="labelShow ? item['label'] : ''" :prop="item['prop']" v-for="(item, index) in componentList"
                    :key="'login-form-item__' + index">
        <el-input v-if="item['type'] === 'input'" class="w-100" v-model="form[item['prop']]"
                  :placeholder="item['placeholder']"/>
        <el-input v-if="item['type'] === 'password'" class="w-100" v-model="form[item['prop']]"
                  :placeholder="item['placeholder']" type="password"/>
        <el-select v-if="item['type'] === 'select'" class="w-100" v-model="form[item['prop']]"
                   :placeholder="item['placeholder']">
          <el-option v-for="(option, optionIndex) in item['items']"
                     :key="'select-option__group' + index + 'key__' + optionIndex" :label="option['label']"
                     :value="option['value']"/>
        </el-select>
        <el-input v-if="item['type'] === 'phone'" class="w-100" v-model="form[item['prop']]">
          <template #append>
            <el-button @click="handlePhoneSendMsg(item)">获取验证码</el-button>
          </template>
        </el-input>
        <el-input v-if="item['type'] === 'email'" class="w-100" v-model="form[item['prop']]">
          <template #append>
            <el-button @click="handleMailSendMsg(item)">获取验证码</el-button>
          </template>
        </el-input>
        <el-input v-if="item['type'] === 'code'" class="w-100 img" v-model="form[item['prop']]">
          <template #append>
            <img class="code-img" alt="图形验证码" :src="item['codeImage']" @click="handleGetCode(item)" />
          </template>
        </el-input>
      </el-form-item>
      <el-form-item label-position="left">
        <el-button type="primary" class="w-100" @click="handleSubmit">{{ submitText }}</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<style lang="scss">
.component-login-form-container {
  width: 300px;

  .w-100 {
    width: 100%;

    &.img {
      .el-input-group__append {
        padding: 0;

        .code-img {
          width: 100px;
        }
      }
    }
  }
}
</style>
